/*
 * @描述: 
 * @创建者: kilomChou
 * @Date: 2021-04-11 16:57:02
 * @最后编辑: kilomChou
 * @LastEditTime: 2021-05-15 11:23:55
 */
import Food, { FoodType } from "./Food"
import SnakeNode from "../snake/SnakeNode"
import Snake from "../snake/Snake"
import World from "./World"
import { Util } from "../../util/Util"
import { IRect, Vec2 } from "../../core/vec2/Vec2"
const [v2] = [Vec2];

/** 区块 */
export default class Chunk implements IRect {

    constructor(
        /**所在世界 */
        readonly world: World,
        rect: IRect) {

        v2.rectAs(this, rect);
        this._foodMap.set(FoodType.normal, new Set());
        this._foodMap.set(FoodType.snake, new Set());
    }

    x: number;
    y: number;
    w: number;
    h: number;

    /** 普通食物的数量 由worldFoodMgr管理 用来控制区块的最大食物容纳数量 */
    normalFoodCount = 0;

    /** 食物映射 */
    private _foodMap = new Map<FoodType, Set<Food>>();
    /** 蛇节点映射 */
    private _snakeNodeMap = new Map<Snake, Set<SnakeNode>>();

    /** 添加食物 */
    addFood(food: Food) {
        this._foodMap.get(food.type).add(food);
    }

    /** 移除食物 */
    removeFood(food: Food) {
        this._foodMap.get(food.type).delete(food);
    }

    /** 添加蛇节点 */
    addSnakeNode(node: SnakeNode) {
        let nodes = this._snakeNodeMap.get(node.snake);
        !nodes && this._snakeNodeMap.set(node.snake, nodes = new Set<SnakeNode>());
        nodes.add(node);
    }

    /** 移除蛇节点 */
    removeSnakeNode(node: SnakeNode) {
        let nodes = this._snakeNodeMap.get(node.snake)
        if (nodes) {
            nodes.delete(node)
            //该蛇在此区块的节点数为0 将蛇从map中移除
            if (nodes.size == 0) {
                this._snakeNodeMap.delete(node.snake)
            }
        }
    }


    // ============ PUBLIC ============

    /** 蛇节点集合 */
    get snakeNodeMap() { return this._snakeNodeMap }

    /** 蛇节点数量 */
    get snakeNodeCount() { return this._snakeNodeMap.size }

    /** 区块内的蛇集合 */
    get snakes() { return Array.from(this._snakeNodeMap.keys()) }

    /** 区块内的蛇节点集合 */
    get snakeNodes() {
        let nodes: SnakeNode[] = []
        this._snakeNodeMap.forEach(ns => nodes = Util.arrConcatSet(nodes, ns))
        return nodes
    }

    /** 获取区块内的食物 */
    get foods() {
        let foods: Food[] = [];
        this._foodMap.forEach(fs => foods = foods.concat(Array.from(fs)))
        return foods
    }

    /** 获取包含指定蛇集合的蛇节点集合 */
    getSnakeNodesInclude(include: Snake[]) {
        let snakeNodes: SnakeNode[] = []
        include.forEach(snake => {
            let nodeSet = this._snakeNodeMap.get(snake)
            if (nodeSet) {
                snakeNodes = snakeNodes.concat(Array.from(nodeSet))
            }
        })
        return snakeNodes
    }

    /** 获取不包含指定蛇集合的蛇节点集合 */
    getSnakeNodesExclude(exclude: Snake[]) {
        let include = Array.from(this._snakeNodeMap.keys())
        exclude.forEach(snake => Util.arrRemoveItem(include, snake))
        return this.getSnakeNodesInclude(include)
    }

    /** 获取包含指定蛇集合的蛇节点映射 */
    getSnakeNodeMapInclude(include: Snake[]) {
        let snakeNodeMap = new Map<Snake, Set<SnakeNode>>()
        include.forEach(snake => {
            let nodeSet = this._snakeNodeMap.get(snake)
            if (nodeSet) {
                snakeNodeMap.set(snake, nodeSet)
            }
        })
        return snakeNodeMap
    }

    /** 获取不包含指定蛇集合的蛇节点映射 */
    getSnakeNodeMapExclude(exclude: Snake[]) {
        let include = Array.from(this._snakeNodeMap.keys())
        exclude.forEach(snake => Util.arrRemoveItem(include, snake))
        return this.getSnakeNodeMapInclude(include)
    }

}
